package com.semidata.trp.business.data;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.ibatis.session.SqlSession;

import com.semidata.rtd.core.log.Logger;
import com.semidata.trp.business.mapper.BusinessMapper;
import com.semidata.trp.business.model.AlgorithmModel;
import com.semidata.trp.business.model.AllocationModel;
import com.semidata.trp.business.model.AreaModel;
import com.semidata.trp.business.model.FixedCostModel;
import com.semidata.trp.business.model.MaterialModel;
import com.semidata.trp.business.model.MaterialWeightModel;
import com.semidata.trp.business.model.OrganizationModel;
import com.semidata.trp.business.model.PositionModel;
import com.semidata.trp.business.model.ResourceAreaModel;
import com.semidata.trp.business.model.ResourceHourModel;
import com.semidata.trp.business.model.ResourceModel;
import com.semidata.trp.business.model.ResourcePriceModel;
import com.semidata.trp.business.model.StrategyAreaModel;
import com.semidata.trp.business.model.StrategyHotword;
import com.semidata.trp.business.model.StrategyHourModel;
import com.semidata.trp.business.model.StrategyModel;
import com.semidata.trp.business.model.TrafficModel;
import com.semidata.trp.business.report.KeyWord;
import com.semidata.trp.business.utils.SessionUtils;
import com.semidata.trp.message.business.Business;

public class DataLoader {

	private long organizationLastUpdate = 0;
	private long materialLastUpdate = 0;
	private long positionLastUpdate = 0;
	private long algorithmLastUpdate = 0;
	private long trafficLastUpdate = 0;
	private long resourceLastUpdate = 0;
	private long strategyLastUpdate = 0;
	private long fixedcostLastUpdate = 0;

	private Map<Integer, String> areas = new HashMap<>();

	public DataLoader() {
		try {
			SqlSession session = SessionUtils.getSession();
			loadAreas(session);
			SessionUtils.close(session);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public void loadAreas(SqlSession session) {
		Logger.log("INFO", "load area data...");
		long s = System.currentTimeMillis();
		BusinessMapper mapper = session.getMapper(BusinessMapper.class);

		List<AreaModel> list = mapper.getAreas();

		for (AreaModel area : list) {
			areas.put(area.getId(), area.getCode());
		}

		Logger.log(
				"INFO",
				"load area completely, time cost = "
						+ (System.currentTimeMillis() - s) + " ms");
	}

	public List<OrganizationModel> loadOrganizations(SqlSession session) {
		long s = 0;
		if (organizationLastUpdate == 0) {
			Logger.log("INFO", "load organization data...");
			s = System.currentTimeMillis();
		}

		BusinessMapper mapper = session.getMapper(BusinessMapper.class);
		List<OrganizationModel> list = mapper.getOrganizations(new Timestamp(
				organizationLastUpdate));

		if (!list.isEmpty()) {
			organizationLastUpdate = list.get(list.size() - 1).getLastUpdate()
					.getTime();
		}

		if (s != 0) {
			Logger.log("INFO", "load organization completely, time cost = "
					+ (System.currentTimeMillis() - s) + " ms");
		}
		return list;
	}

	public List<MaterialModel> loadMaterials(SqlSession session) {
		long s = 0;
		if (materialLastUpdate == 0) {
			Logger.log("INFO", "load material data...");
			s = System.currentTimeMillis();
		}

		BusinessMapper mapper = session.getMapper(BusinessMapper.class);
		List<MaterialModel> list = mapper.getMaterials(new Timestamp(
				materialLastUpdate));
		if (!list.isEmpty()) {
			materialLastUpdate = list.get(list.size() - 1).getLastUpdate()
					.getTime();
		}

		if (s != 0) {
			Logger.log("INFO", "load material completely, time cost = "
					+ (System.currentTimeMillis() - s) + " ms");
		}
		return list;
	}

	public List<PositionModel> loadPositions(SqlSession session) {
		long s = 0;
		if (positionLastUpdate == 0) {
			Logger.log("INFO", "load position data...");
			s = System.currentTimeMillis();
		}

		BusinessMapper mapper = session.getMapper(BusinessMapper.class);
		List<PositionModel> list = mapper.getPositions(new Timestamp(
				positionLastUpdate));
		if (!list.isEmpty()) {
			positionLastUpdate = list.get(list.size() - 1).getLastUpdate()
					.getTime();
		}

		if (s != 0) {
			Logger.log("INFO", "load position completely, time cost = "
					+ (System.currentTimeMillis() - s) + " ms");
		}
		return list;
	}

	public List<TrafficModel> loadTraffics(SqlSession session) {
		long s = 0;
		if (trafficLastUpdate == 0) {
			Logger.log("INFO", "load traffic data...");
			s = System.currentTimeMillis();
		}

		BusinessMapper mapper = session.getMapper(BusinessMapper.class);
		List<TrafficModel> list = mapper.getTraffics(new Timestamp(
				trafficLastUpdate));
		if (!list.isEmpty()) {
			trafficLastUpdate = list.get(list.size() - 1).getLastUpdate()
					.getTime();
		}

		if (s != 0) {
			Logger.log("INFO", "load traffic completely, time cost = "
					+ (System.currentTimeMillis() - s) + " ms");
		}
		return list;
	}

	public List<ResourceModel> loadResources(SqlSession session) {
		long s = 0;
		if (resourceLastUpdate == 0) {
			Logger.log("INFO", "load resource data...");
			s = System.currentTimeMillis();
		}

		BusinessMapper mapper = session.getMapper(BusinessMapper.class);
		List<ResourceModel> list = mapper.getResources(new Timestamp(
				resourceLastUpdate));

		if (list.isEmpty())
			return list;

		Map<Integer, ResourceModel> resources = new HashMap<>();

		List<Integer> ids = new ArrayList<>();
		for (ResourceModel model : list) {
			if (!model.isDeleted()) {
				ids.add(model.getId());
			}
			resources.put(model.getId(), model);
		}
		List<ResourceAreaModel> areas = mapper.getResourceAreas(ids);
		List<ResourceHourModel> hours = mapper.getResourceHours(ids);
		List<AllocationModel> allocations = mapper.getAllocations(ids);
		for (AllocationModel allocation : allocations) {
			ResourceModel resource = resources.get(allocation.getResourceId());
			if (resource == null)
				continue;
			resource.addAllocation(allocation);
		}
		for (ResourceAreaModel ram : areas) {
			ResourceModel resource = resources.get(ram.getResourceId());
			if (resource == null)
				continue;
			String code = this.areas.get(ram.getAreaId());

			if (code != null)
				resource.getAreas().add(code);
		}
		for (ResourceHourModel rhm : hours) {
			ResourceModel resource = resources.get(rhm.getResourceId());
			if (resource == null)
				continue;
			resource.getHours().add(rhm.getHour());
		}
		resourceLastUpdate = list.get(list.size() - 1).getLastUpdate()
				.getTime();

		if (s != 0) {
			Logger.log("INFO", "load resource completely, time cost = "
					+ (System.currentTimeMillis() - s) + " ms");
		}
		return list;
	}

	public List<StrategyModel> loadStrategies(SqlSession session) {
		long s = 0;
		if (strategyLastUpdate == 0) {
			Logger.log("INFO", "load strategy data...");
			s = System.currentTimeMillis();
		}

		BusinessMapper mapper = session.getMapper(BusinessMapper.class);
		List<StrategyModel> list = mapper.getStrategies(new Timestamp(
				strategyLastUpdate));

		if (list.isEmpty())
			return list;

		Map<Integer, StrategyModel> strategies = new HashMap<>();

		List<Integer> ids = new ArrayList<>();
		for (StrategyModel model : list) {
			if (!model.isDeleted())
				ids.add(model.getId());
			strategies.put(model.getId(), model);
		}

		List<ResourcePriceModel> resourcePrices = mapper.getResourcePrices(ids);
		List<MaterialWeightModel> materialWeights = mapper
				.getMaterialWeights(ids);
		List<StrategyAreaModel> strategyAreas = mapper.getStrategyAreas(ids);
		List<StrategyHourModel> strategyHours = mapper.getStrategyHours(ids);

		for (ResourcePriceModel resourcePrice : resourcePrices) {
			StrategyModel strategy = strategies.get(resourcePrice
					.getStrategyId());
			if (strategy == null)
				continue;
			strategy.addResourcePrice(resourcePrice);
		}

		for (MaterialWeightModel materialWeight : materialWeights) {
			StrategyModel strategy = strategies.get(materialWeight
					.getStrategyId());
			if (strategy == null)
				continue;
			strategy.addMaterialWeight(materialWeight);
		}

		for (StrategyAreaModel strategyArea : strategyAreas) {
			StrategyModel strategy = strategies.get(strategyArea
					.getStrategyId());
			if (strategy == null)
				continue;
			String code = areas.get(strategyArea.getAreaId());
			if (code != null)
				strategy.addArea(code);
		}

		for (StrategyHourModel strategyHour : strategyHours) {
			StrategyModel strategy = strategies.get(strategyHour
					.getStrategyId());
			if (strategy == null)
				continue;
			strategy.addHour(strategyHour);
		}

		strategyLastUpdate = list.get(list.size() - 1).getLastUpdate()
				.getTime();

		if (s != 0) {
			Logger.log("INFO", "load strategy completely, time cost = "
					+ (System.currentTimeMillis() - s) + " ms");
		}
		return list;
	}

	public Map<Integer, List<Business.KeyWord>> loadStrategyHotword(
			SqlSession sql, List<Integer> strategyIds) {
		Map<Integer, List<Business.KeyWord>> strategyHotword = new HashMap<>();
		if (strategyIds == null || strategyIds.size() == 0)
			return null;
		for (Integer sid : strategyIds)
			strategyHotword.put(sid, new ArrayList<Business.KeyWord>());

		BusinessMapper mapper = sql.getMapper(BusinessMapper.class);
		List<StrategyHotword> hotwords = mapper
				.getStrategyHotwords(strategyIds);
		if (hotwords == null || hotwords.size() == 0)
			return strategyHotword;

		for (StrategyHotword shw : hotwords) {
			String[] keys = shw.getHotword().split("&");
			int keyCount = keys.length;
			String key1 = "", key2 = "", key3 = "";
			if (keyCount >= 1) {
				Business.KeyWord.Builder kw = Business.KeyWord.newBuilder();
				key1 = keys[0];
				if (!key1.trim().isEmpty() && keyCount >= 2) {
					key2 = keys[1];
					if (!key2.trim().isEmpty() && keyCount >= 3) {
						key3 = keys[2];
					}
				}
				if (!key1.trim().isEmpty()) {
					kw.setKeyword1(key1.trim());
					kw.setKeyword2(key2.trim());
					kw.setKeyword3(key3.trim());
					strategyHotword.get(shw.getStrategyId()).add(kw.build());
				}

			}
		}
		return strategyHotword;

	}

	public Map<Integer, FixedCostModel> loadFixedCost(SqlSession session) {
		Map<Integer, FixedCostModel> fixedcost = new HashMap<>();
		BusinessMapper mapper = session.getMapper(BusinessMapper.class);

		Timestamp timestamp = new Timestamp(fixedcostLastUpdate);
		List<FixedCostModel> costs = mapper.getFixedCost(timestamp);
		for (FixedCostModel cost : costs) {
			Integer id = cost.getId();
			fixedcost.put(id, cost);
		}
		if (!fixedcost.isEmpty()) {
			fixedcostLastUpdate = costs.get(costs.size() - 1).getTimestamp()
					.getTime();
		}
		return fixedcost;
	}

	public List<AlgorithmModel> loadAlgorithms(SqlSession session) {
		// TODO Auto-generated method stub
		long s = 0;
		if (algorithmLastUpdate == 0) {
			Logger.log("INFO", "load algorithm data...");
			s = System.currentTimeMillis();
		}

		BusinessMapper mapper = session.getMapper(BusinessMapper.class);
		List<AlgorithmModel> list = mapper.getAlgorithms(new Timestamp(
				algorithmLastUpdate));
		if (!list.isEmpty()) {
			algorithmLastUpdate = list.get(list.size() - 1).getLastUpdate()
					.getTime();
		}

		if (s != 0) {
			Logger.log("INFO", "load algorithm completely, time cost = "
					+ (System.currentTimeMillis() - s) + " ms");
		}
		return list;
	}
}
